package com.ruoyi.publish.manager;


import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.contast.Contast;
import com.ruoyi.publish.config.JenkinsConfig;
import com.ruoyi.publish.domain.BestJenkinsBuilds;
import com.ruoyi.utils.DataTimeUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

@Component
public class JenkinsJarDownloader {

    @Resource
    private JenkinsConfig jenkinsConfig;

    public CompletableFuture<BestJenkinsBuilds>  downloadJAR(String jobName,String downloadUrl,String fileName)  {
        return CompletableFuture.supplyAsync(()->{
// Step 1: 获取最后一次构建成功的信息
            String buildInfoUrl = jenkinsConfig.getJenkinsUrl() + "/job/" + jobName + "/lastSuccessfulBuild/api/json";
            String buildInfoJson = null;
            try {
                buildInfoJson = sendHttpGetRequest(buildInfoUrl);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            // Step 2: 根据构建信息获取拼接jar下载路径
            String artifactUrl = null;
            try {
                artifactUrl = parseArtifactUrl(buildInfoJson,downloadUrl,jobName);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            if (artifactUrl == null) {
                System.err.println("No artifact found in the build.");
                throw  new RuntimeException("Jenkins构建失败，没有找到构建产物");
            }
            // Step 3: 下载jar包到本地
            String localPath= null;
            try {
                localPath = downloadFile(artifactUrl,fileName);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            BestJenkinsBuilds res  = null;
            try {
                res = parseBuildInfo(buildInfoJson);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
            res.setBuildUrl(artifactUrl);
            res.setDownloadUrl(localPath);
            res.setFilePath(localPath);
            res.setFileName(fileName);
            res.setCreateTime(new Date());
            return res;
        });
    }

    private BestJenkinsBuilds parseBuildInfo(String buildInfoJson) throws JsonProcessingException {
        BestJenkinsBuilds res = new BestJenkinsBuilds();
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(buildInfoJson);
        String text = rootNode.get("actions").get(0).get("parameters").get(0).get("value").asText();
        res.setBuildTag(text);
        res.setBuildTimestamp(new Date(rootNode.path("timestamp").asLong()));
        return res;
    }


    /**
     * Send an HTTP GET request and return the response as a string.
     */
    private String sendHttpGetRequest(String url) throws IOException {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(url);
            String auth = jenkinsConfig.getUsername() + ":" + jenkinsConfig.getPassword();
            String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
            request.setHeader("Authorization", "Basic " + encodedAuth);
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                return new String(response.getEntity().getContent().readAllBytes());
            }
        }
    }

    /**
     * Parse the artifact URL from the build info JSON.
     */
    private  String parseArtifactUrl(String buildInfoJson,String downloadUrl,String jobName) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(buildInfoJson);
        JsonNode artifactsNode = rootNode.path("id");
        if (ObjectUtils.allNotNull(artifactsNode)) {
            String relativePath = artifactsNode.asText();
            return jenkinsConfig.getJenkinsUrl() + "job/" + jobName + "/"+relativePath+"/" + downloadUrl;

        }
        return null;
    }

    /**
     * Download a file from a URL and save it to the local path.
     */
    private  String downloadFile(String fileUrl,String fileName) throws IOException {
        String localPath;
        String userHome = System.getProperty("user.home"); // 获取用户主目录
        localPath = userHome + "/"+fileName;  // 保存到用户主目录
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(fileUrl);
            String auth = jenkinsConfig.getUsername() + ":" + jenkinsConfig.getPassword();
            String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
            request.setHeader("Authorization", "Basic " + encodedAuth);
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != HttpStatus.SC_OK) {
                    throw new IOException("Failed to download file. HTTP status code: " + statusCode);
                }
                HttpEntity entity = response.getEntity();
                if (entity == null) {
                    throw new IOException("Response entity is null.");
                }
                try (InputStream inputStream = new BufferedInputStream(entity.getContent());
                     FileOutputStream outputStream = new FileOutputStream(localPath);
                     BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {
                    byte[] buffer = new byte[4096]; // Increase buffer size for better performance
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        bufferedOutputStream.write(buffer, 0, bytesRead);
                    }
                    bufferedOutputStream.flush();
                }
            }
        } catch (IOException e) {
            //logger.error("Error downloading file from URL: " + fileUrl, e);
            throw e;
        }
        return localPath;
    }

    public CompletableFuture<String> downloadFileAsync(String fileUrl, String fileName) {
        return CompletableFuture.supplyAsync(() -> {
            String localPath;
            String userHome = System.getProperty("user.home"); // 获取用户主目录
            localPath = userHome + "/" + fileName;  // 保存到用户主目录

            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                HttpGet request = new HttpGet(fileUrl);
                String auth = jenkinsConfig.getUsername() + ":" + jenkinsConfig.getPassword();
                String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
                request.setHeader("Authorization", "Basic " + encodedAuth);

                try (CloseableHttpResponse response = httpClient.execute(request)) {
                    int statusCode = response.getStatusLine().getStatusCode();
                    if (statusCode != HttpStatus.SC_OK) {
                        throw new IOException("Failed to download file. HTTP status code: " + statusCode);
                    }
                    HttpEntity entity = response.getEntity();
                    if (entity == null) {
                        throw new IOException("Response entity is null.");
                    }

                    try (InputStream inputStream = new BufferedInputStream(entity.getContent());
                         FileOutputStream outputStream = new FileOutputStream(localPath);
                         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {
                        byte[] buffer = new byte[4096]; // Increase buffer size for better performance
                        int bytesRead;
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            bufferedOutputStream.write(buffer, 0, bytesRead);
                        }
                        bufferedOutputStream.flush();
                    }
                }
            } catch (IOException e) {
                //logger.error("Error downloading file from URL: " + fileUrl, e);
                throw new RuntimeException("Error downloading file", e);
            }

            return localPath;
        });
    }

}
